﻿Imports WiremetModel.Entities.SupplyOrders
Imports WiremetModel.Entities
Imports WiremetModel.Specification.SupplyOrders
Imports GMap.NET
Imports GMap.NET.WindowsForms
Imports InputValidation.GeneralRules
Imports InputValidation
Imports System.ComponentModel

Public Class MiscellaneousOrderInputDialog

    Private _unitOfWork As UnitOfWork
    Private _inputValidator As InputValidator

    Private _miscellaneousOrder As MiscellaneousOrder
    Public Property MiscellaneousOrder() As MiscellaneousOrder
        Get
            Return _miscellaneousOrder
        End Get
        Set(ByVal value As MiscellaneousOrder)
            _miscellaneousOrder = value
        End Set
    End Property

    Private _supplierLocationOverlay As GMapOverlay

    Public Sub New(ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        InitializeSupplierAddressMap()
        _inputValidator = New InputValidator()
        '_unitOfWork = New UnitOfWork()
        _unitOfWork = unitOfWork
        _miscellaneousOrder = New MiscellaneousOrder()
        ClearErrorLabels()
        RefreshViewData()
        dtp_ExpectedDeliveryDate.MinDate = New Date(Now.Year, Now.Month, Now.Day)
    End Sub

    Public Sub New(ByVal miscellaneousOrder As MiscellaneousOrder, ByRef unitOfWork As UnitOfWork)
        Me.New(unitOfWork)

        cmb_Supplier.SelectedItem = miscellaneousOrder.Supplier
        cmb_Currency.SelectedItem = miscellaneousOrder.Currency
        dtp_ExpectedDeliveryDate.MinDate = If(miscellaneousOrder.ExpectedDeliveryDate.HasValue AndAlso miscellaneousOrder.ExpectedDeliveryDate < miscellaneousOrder.SubmitDate, miscellaneousOrder.ExpectedDeliveryDate.Value, miscellaneousOrder.SubmitDate.Date)
        dtp_ExpectedDeliveryDate.Checked = miscellaneousOrder.ExpectedDeliveryDate.HasValue
        dtp_ExpectedDeliveryDate.Value = If(miscellaneousOrder.ExpectedDeliveryDate.HasValue, miscellaneousOrder.ExpectedDeliveryDate.Value, Now)
        tb_OrderNote.Text = miscellaneousOrder.Note

        Dim supplierAddress As SupplierAddress = miscellaneousOrder.Supplier.SupplierAddresses.FirstOrDefault(Function(x) x.Address.Id = miscellaneousOrder.SubmitAddress.Id)
        If Not IsNothing(supplierAddress) Then
            Dim supplierAddressIndex As Integer = lb_SupplierAddress.FindString(supplierAddress.Description)
            If Not IsNothing(supplierAddressIndex) Then
                lb_SupplierAddress.SelectedIndex = supplierAddressIndex
            End If
        Else
            lb_SupplierAddress.ClearSelected()
        End If

        gb_OrderInputData.Text = "Zamówienie: " & miscellaneousOrder.OrderNumber

        _miscellaneousOrder = miscellaneousOrder
        RefreshOrderLineTable(miscellaneousOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

    End Sub

    'Private Sub MiscellaneousOrderInputDialog_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    '    _unitOfWork.Dispose()
    'End Sub

    Private Sub ClearErrorLabels()
        lbl_CurrencyError.Text = String.Empty
        lbl_SupplierError.Text = String.Empty
    End Sub


    Private Sub InitializeComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))
        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1
    End Sub


    Private Sub InitializeSupplierAddressMap()

        GMap_SupplierAddress.MapProvider = MapProviders.GoogleMapProvider.Instance
        GMaps.Instance.Mode = AccessMode.ServerAndCache
        GMap_SupplierAddress.ForceDoubleBuffer = True
        GMap_SupplierAddress.Zoom = 8
        _supplierLocationOverlay = New GMapOverlay(GMap_SupplierAddress, "supplierLocationOverlay")
        GMap_SupplierAddress.Overlays.Add(_supplierLocationOverlay)

    End Sub


    Private Sub RefreshViewData()
        Dim supplierRepository As New Repository(Of Supplier)(_unitOfWork)
        Dim currencyRepository As New Repository(Of OEM.Waluta)(_unitOfWork)

        Dim supplierList As IEnumerable(Of Supplier) = supplierRepository.GetAll()
        Dim currencyList As IEnumerable(Of OEM.Waluta) = currencyRepository.GetAll()

        InitializeComboBox(cmb_Supplier, supplierList)
        InitializeComboBox(cmb_Currency, currencyList)

    End Sub


    Private Sub EnsureSupplierIsSelected()
        If IsNothing(cmb_Supplier.SelectedItem) Then
            Throw New EntityDataInputException("Proszę, wybierz dostawcę, aby kontynuować.")
        End If
    End Sub


    Private Sub cmb_Supplier_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Supplier.SelectedIndexChanged
        Dim selectedSupplier As Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
        If Not IsNothing(selectedSupplier) Then
            lb_SupplierAddress.DataSource = selectedSupplier.SupplierAddresses
        Else
            lb_SupplierAddress.DataSource = Nothing
        End If
    End Sub

    Private Function GetSelectedSupplierAddress() As SupplierAddress
        Dim selectedSupplier As Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
        If Not IsNothing(selectedSupplier) Then
            Return CType(lb_SupplierAddress.SelectedValue, SupplierAddress)
        End If
        Return Nothing
    End Function

    Private Sub lb_SupplierAddress_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles lb_SupplierAddress.SelectedIndexChanged
        Dim supplierAddress As SupplierAddress = GetSelectedSupplierAddress()
        If Not IsNothing(supplierAddress) Then
            tb_SupplierAddress.Text = supplierAddress.Address.ToString()
            Dim addressLocation As New PointLatLng(supplierAddress.Address.Latitude, supplierAddress.Address.Longitude)
            Dim marker As GMapMarker = New Markers.GMapMarkerGoogleRed(addressLocation)
            _supplierLocationOverlay.Markers.Clear()
            marker.ToolTipText = supplierAddress.Supplier.CompanyName
            marker.ToolTipMode = MarkerTooltipMode.Always
            _supplierLocationOverlay.Markers.Add(marker)
            GMap_SupplierAddress.ZoomAndCenterMarkers(_supplierLocationOverlay.Id)
            GMap_SupplierAddress.Zoom = 12
        Else
            tb_SupplierAddress.Text = String.Empty
            _supplierLocationOverlay.Markers.Clear()
            GMap_SupplierAddress.ZoomAndCenterMarkers(_supplierLocationOverlay.Id)
            GMap_SupplierAddress.Zoom = 0
        End If
    End Sub




#Region "Order lines"


    Private Sub RefreshOrderLineTable(ByVal orderLineList As IEnumerable(Of MiscellaneousOrderLine), ByVal currency As OEM.Waluta)
        Dim currencyToString As String = If(IsNothing(currency), String.Empty, currency.Nazwa & "/")
        dgv_MiscellaneousOrderLine.Rows.Clear()
        For Each orderLine As MiscellaneousOrderLine In orderLineList.OrderBy(Function(x) x.Product.Name).OrderBy(Function(x) x.Product.ProductType.Name)
            Dim rowIndex As Integer = dgv_MiscellaneousOrderLine.Rows.Add(
                orderLine.Id,
                orderLine.Product.ProductType.Name,
                orderLine.Product.Name,
                orderLine.Quantity & " " & orderLine.MeasureUnit.Jednostka,
                orderLine.UnitPrice.ToString() & " " & currencyToString & orderLine.MeasureUnit.Jednostka,
                Math.Round(orderLine.UnitPrice * orderLine.Quantity, 2).ToString() & If(IsNothing(currency), String.Empty, " " & currency.Nazwa)
            )
            dgv_MiscellaneousOrderLine.Rows(rowIndex).Tag = orderLine
        Next

        ts_lbl_TotalCost.Text = "Razem: " & orderLineList.Sum(Function(x) Math.Round(x.UnitPrice * x.Quantity, 2)).ToString() & If(IsNothing(currency), String.Empty, " " & currency.Nazwa)
    End Sub


    Private Sub EnsureOrderLineIsSelected()
        If dgv_MiscellaneousOrderLine.SelectedRows.Count = 0 Then
            Throw New EntityDataInputException("Proszę, wybierz pozycję zamówienia, aby kontynuować.")
        End If
    End Sub

    Private Function GetSelectedMiscellaneousOrderLine() As MiscellaneousOrderLine
        Return CType(dgv_MiscellaneousOrderLine.SelectedRows(0).Tag, MiscellaneousOrderLine)
    End Function


    Private Sub ts_btn_AddOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddOrderLine.Click
        Try
            Dim miscellaneousOrderLineInputDialog As New MiscellaneousOrderLineInputDialog(_unitOfWork)
            If miscellaneousOrderLineInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then

                Dim miscellaneousOrderLine = miscellaneousOrderLineInputDialog.MiscellaneousOrderLine
                miscellaneousOrderLine.MiscellaneousOrder = MiscellaneousOrder

                MiscellaneousOrder.OrderLines.Add(miscellaneousOrderLine)
                RefreshOrderLineTable(MiscellaneousOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_EditOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_EditOrderLine.Click
        Try
            Dim selectedMiscellaneousOrderLine As MiscellaneousOrderLine = GetSelectedMiscellaneousOrderLine()
            Dim miscellaneousOrderLineInputDialog As New MiscellaneousOrderLineInputDialog(_unitOfWork, selectedMiscellaneousOrderLine)
            If miscellaneousOrderLineInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then

                selectedMiscellaneousOrderLine = miscellaneousOrderLineInputDialog.MiscellaneousOrderLine
                RefreshOrderLineTable(MiscellaneousOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_DeleteOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_DeleteOrderLine.Click
        Try
            Dim selectedMiscellaneousOrderLine As MiscellaneousOrderLine = GetSelectedMiscellaneousOrderLine()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)

            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then

                MiscellaneousOrder.OrderLines.Remove(selectedMiscellaneousOrderLine)
                RefreshOrderLineTable(MiscellaneousOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub


#End Region



#Region "Input validation"


    Private Sub cmb_Supplier_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_Supplier.Validating
        Dim notNullableComboBoxValidatingSpecification As New NotNullableComboBoxValidatingSpecification(Of Supplier)
        _inputValidator.ValidateComboBox(cmb_Supplier, e, lbl_SupplierError, notNullableComboBoxValidatingSpecification)
    End Sub

    Private Sub cmb_Currency_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_Currency.Validating
        Dim notNullableComboBoxValidatingSpecification As New NotNullableComboBoxValidatingSpecification(Of OEM.Waluta)
        _inputValidator.ValidateComboBox(cmb_Currency, e, lbl_CurrencyError, notNullableComboBoxValidatingSpecification)
    End Sub

    Private Sub cmb_Supplier_validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_Supplier.Validated
        lbl_SupplierError.Text = String.Empty
    End Sub

    Private Sub cmb_Currency_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_Currency.Validated
        lbl_CurrencyError.Text = String.Empty
    End Sub



#End Region

    Private Sub btn_Accept_Click(sender As System.Object, e As System.EventArgs) Handles btn_Accept.Click
        Try
            If Not ValidateChildren() Then
                Throw New EntityDataInputException("Podane dane są nieprawidłowe." & vbNewLine &
                                                   "Popraw je i spróbuj ponownie.")
            End If

            If dgv_MiscellaneousOrderLine.Rows.Count = 0 Then
                Throw New EntityDataInputException("Proszę, dodaj pozycje zlecenia, aby kontynuować")
            End If

            If lb_SupplierAddress.SelectedItems.Count = 0 Then
                Throw New EntityDataInputException("Proszę, wybierz adres dostawcy, aby kontynuować")
            End If

            Dim currency As OEM.Waluta = CType(cmb_Currency.SelectedItem, OEM.Waluta)
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?" & vbNewLine &
                                                                           "Całkowity koszt zamówienia: " & MiscellaneousOrder.OrderLines.Sum(Function(x) Math.Round(x.UnitPrice * x.Quantity, 2)).ToString() & If(IsNothing(currency), String.Empty, " " & currency.Nazwa),
                                                                           "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then

                Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)
                Dim miscellaneousOrderFromMonthSpecification As New OrderFromMonthSpecification(Of MiscellaneousOrder)(Date.Now)
                Dim orderNumber As Integer = Now.Year * 100000 + Now.Month * 1000 + miscellaneousOrderRepository.GetAll().Where(Function(x) x.SubmitDate.Year = Now.Year AndAlso x.SubmitDate.Month = Now.Month).Count() + 1


                With MiscellaneousOrder
                    .Employee = User
                    .ExpectedDeliveryDate = If(dtp_ExpectedDeliveryDate.Checked, dtp_ExpectedDeliveryDate.Value, CType(Nothing, DateTime?))
                    .Note = If(String.IsNullOrEmpty(tb_OrderNote.Text.Trim()), Nothing, tb_OrderNote.Text.Trim())
                    '.OrderNumber = CStr(Date.Now.Year * 100000 + Date.Now.Month * 1000 + miscellaneousOrderRepository.GetAllMatching(miscellaneousOrderFromMonthSpecification).Count() + 1)
                    .OrderNumber = If(String.IsNullOrEmpty(.OrderNumber), orderNumber.ToString() & "M", .OrderNumber)
                    .SubmitAddress = GetSelectedSupplierAddress().Address
                    .SubmitDate = Date.Now()
                    .Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
                    .Currency = currency
                End With

                DialogResult = Windows.Forms.DialogResult.OK
            End If
        Catch ex As EntityDataInputException
            MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub btn_Cancel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Cancel.Click
        DialogResult = Windows.Forms.DialogResult.Cancel
    End Sub


    Private Sub cmb_Currency_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Currency.SelectedIndexChanged
        RefreshOrderLineTable(MiscellaneousOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))
    End Sub


End Class